#ifndef NONLINEAR_CG_STATE_H
#define NONLINEAR_CG_STATE_H


#include "PArray.h"
#include "IterationState.h"
#include "TetrahedronState.h"

class NonlinearCGState: public IterationState
{
public:

	Real residual_tolerance_;
	Array<Real> search_dir_;
	Array<Real> mat_times_search_dir_;
	Array<Real> residual_;

	Array<Real> try_displacement_;
	Array<Real> try_residual_;
	Array<Real> prev_residual_;  


	bool no_more_improvement_b_;	// set to true, if CG can't improve current sol.
	bool restart_b_;
	int last_restart_; 
	Real residual_len_;
	Real prev_residual_len_;

	Real (*step_length_function_)(NonlinearCGState *state, DeformationState const*);

	NonlinearCGState ();

	virtual void IterationStep(DeformationState*);
	virtual void UpdateResidual (DeformationState const*);
	virtual void PrintNodes ()const;
	virtual void Print () const;


	virtual void CalculateResidualAndDerivative (Real*,Real*, Real, DeformationState const*);

	virtual bool GoodSolution (DeformationState const*) const;

	virtual void Reinit (DeformationState const*);
	virtual ~NonlinearCGState ();

protected:
	LinkArray< Array<Real> > VectorVariables ();

	static  Real NewtonMethod (NonlinearCGState*, DeformationState const*);
	static  Real SecantMethod (NonlinearCGState*, DeformationState const*);
	static Real LinearAlpha (NonlinearCGState*, DeformationState const*);

	Real CalculateTryResidual (Real, DeformationState const*);

	void GraphAlpha (Real, DeformationState const*);
	int Dimension () const;
};



#endif 